LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;

entity DataCacheControlUnit is
       port (
                  CLK             	: in bit;
                  RESET           	: in bit;
                  --addr            : in bit_vector(4 downto 0);
                  READSIG         	: in bit;
                  WRITESIG        	: in bit;
                  HIT             	: 	in bit;
                  VALID           	: 	in bit_vector(7 downto 0);
                  DIRTY           	: 	in bit_vector(7 downto 0);
                  ADDR				: 	in bit_vector(31 downto 0); -- Access address
                  DataToMem			:	in bit_vector(127 downto 0); -- the data to write to the data memory.
                  DataFromMem		:	in bit_vector(127 downto 0); -- the data comes from the data memory.
                  --data_t_mem      : in bit_vector(127 downto 0); -- the exact data is stored in the low 32 bits
                  --data_f_cpu      : in bit_vector(127 downto 0);
                  --data_f_mem      : in bit_vector(127 downto 0);
                  TAG           : in bit_vector(24 downto 0); -- ADDR[31..7]
                  --fwb             : in bit;
                  
                  CACHEFREE      : out bit;
                  WRITEENTRY      : out bit; -- Send 'Write Enable' to cache entry stack. 
				  REPLACEENTRY		: out bit;
                  ENTRYSEL        	: out std_logic_vector(2 downto 0);
                  READLN          	: out bit;
                  WRITEMEM        : out bit; -- Update Memory
                  MEMADDR         : out bit_vector(31 downto 0); -- The update target address
                  MEMWDATA        : out bit_vector(127 downto 0); -- The value to update the memory
                  SELECTADDR    : out bit; -- address come from ? 0-outside 1-inside
                  DATAIN          : out bit_vector(127 downto 0);
                  ADDRIN          : out bit_vector(31 downto 0)
       );

      -- type status is (FREE, RMWB, RMF, WMWB, WMF, WD, FDWB, F_WB);
       type status is (FREE, BUSY);

       signal current             : status;
       signal nextToRep               : integer := 0;
       -- signal next_rep            : integer;
       signal tmp_wdata           : bit_vector(127 downto 0);
        --signal tmp_waddr           : bit_vector(4 downto 0);
       
        --constant delay             : integer := 5;

end DataCacheControlUnit;


Architecture cc of DataCacheControlUnit is 
begin
  process (CLK, RESET)
  begin
    if RESET = '0' then
      current <= FREE;
      REPLACEENTRY <= '0';
      CACHEFREE <= '1';
      WRITEMEM <= '0';
      WRITEENTRY <= '0';
     -- count <= 0;
      READLN <= '0';
     -- select_addr <= '0';
    elsif ((CLK' event) and (CLK = '0')) then
      if (current = FREE) then
	     -- if (fwb = '1') then
	      --   cachefree <= '0';
	       --  current <= FDWB;
	     if (READSIG = '1') then
			if HIT = '1' then
				current <= FREE;
				CACHEFREE <= '1';
				REPLACEENTRY <= '0';
			else -- read miss
				CACHEFREE <= '0';
				MEMADDR <= ADDR;
				if ( (VALID(nextToRep)='0') and (DIRTY(nextToRep)='0') ) then
		            -- memaddr(4 downto 3) <= "00";
		            -- memaddr(2 downto 0) <= addr(4 downto 2);
		            -- ADDRIN <= ADDR;
		            current <= BUSY;
		            DATAIN <= DataFromMem;
		            
		            ENTRYSEL <= CONV_STD_LOGIC_VECTOR(nextToRep, 3);-- select to replace
		            REPLACEENTRY <= '1';
		            READLN <= '0';
		            
		            nextToRep <= nextToRep + 1;
		            
		            current <= FREE;
		            --count <= delay;
	            else
		            READLN <= '1';
		            SELECTADDR <= '1';
		            	            
		            ENTRYSEL <= CONV_STD_LOGIC_VECTOR(nextToRep, 3);-- select to replace
		            
		            
--		            addrin(4 downto 2) <= tagin;
--		            addrin(1 downto 0) <= "00";
--		            tmp_waddr <= addr;
--		            memaddr(4 downto 3) <= "00";
--		            memaddr(2 downto 0) <= tagin;
--		            current <= BUSY;
		            --count <= delay + 1;
	             end if;
			end if;
	     end if;
	   
	     if (WRITESIG = '1') then
	         tmp_wdata <= DataToMem;
	         CACHEFREE <= '0';
	         if HIT = '1' then   -- The write destination is currently cached
					WRITEENTRY <= '1'; 
					SELECTADDR <= '1';
					ADDRIN <= ADDR;	
					DATAIN <= DataToMem;   
					current <= BUSY;
	         else -- The write destination is miss now.
				 if ( (VALID(nextToRep)='0') or (DIRTY(nextToRep)='0') ) then -- invalid or data same with that in mem
	                MEMADDR(4 downto 3) <= "00";
	                MEMADDR(2 downto 0) <= addr(6 downto 4);
	                --addrin <= addr;
	                current <= BUSY;
	               -- count <= delay;
	            else
--	                readln <= '1';
--	                addrin(4 downto 2) <= tagin; -- place data in the lowest part 
--	                addrin(1 downto 0) <= "00";
--	                tmp_waddr <= addr;
--	                memaddr(4 downto 3) <= "00";
--	                memaddr(2 downto 0) <= tagin;
--	                current <= BUSY;
--	                count <= delay + 1;
	            end if;
	                  
	         end if;
	       
		 end if;
	   end if;
	 end if;
    --ENTRYSEL <= CONV_STD_LOGIC_VECTOR(next_rep, 3);
  end process;
end;
